/*
 heat-spectral lib. solves time-dependent PDEs using SEM-NI method.
 Copyright (C) 2009, Altieri Michele and Stefanoni Andrea
 Copyright (C) 2008, Proverbio Alessandro and Radice David

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef MACRO_HPP
#define MACRO_HPP 1

/**
    \file macro.hpp
    \brief Usefull pre-processor macros

    Macros with a name begining with SPECTRAL should be considered
    as "private macros" and are not intended for the use of the final user.
*/

// ******************************************************************
// Type Name Builders
// ******************************************************************
// Macro to easily use the above functionals
// 1. L2 Error functional
// 2. H1 Error functional
// 3. Time dependent L2 Error functional
// 4. Time dependent H1 Error functional
// 5. L2 Norm functional
// 6. H1 SemiNorm functional
// ******************************************************************

/// L2 Error type builder
#define MAKE_L2_ERROR(SOLUTION,MESH)                                    \
         typedef spectral::L2Error <                                    \
                                     SOLUTION,                          \
                                     MESH                               \
                                   >

/// H1 Error type builder
#define MAKE_H1_ERROR(SOLUTION,SOLUTION_X,SOLUTION_Y,MESH)              \
         typedef spectral::H1Error <                                    \
                                     SOLUTION,                          \
                                     SOLUTION_X,                        \
                                     SOLUTION_Y,                        \
                                     MESH                               \
                                   >

/// Time dependent L2 Error type builder
#define MAKE_L2TIME_ERROR(SOLUTION,MESH)					\
	typedef spectral::L2Error<					\
				  SOLUTION,				\
				  MESH,					\
				  true					\
				 >

/// Time dependent H1 Error type builder
#define MAKE_H1TIME_ERROR(SOLUTION,SOLUTION_X,SOLUTION_Y,MESH)		\
	typedef spectral::H1Error <					\
				   SOLUTION,				\
				   SOLUTION_X,				\
				   SOLUTION_Y,				\
				   MESH,				\
				   true					\
				  >

/// L2 Norm type builder
#define MAKE_L2_NORM(MESH)                                              \
         typedef spectral::L2Norm <                                     \
                                    MESH                                \
                                  >

/// H1 Seminorm type builder
#define MAKE_H1_SEMINORM(MESH)                                          \
         typedef spectral::H1SemiNorm <                                 \
                                        MESH                            \
                                      >

/// H1 Norm type builder
#define MAKE_H1_NORM(MESH)                                              \
         typedef spectral::H1Norm <                                     \
                                    MESH                                \
                                  >

// ******************************************************************
// Helper Macros
// ******************************************************************
// 1. Quadratic form \int (a-b)^2
// 2. Restriction + quadratic form
// 3. Operator + restriction + quadratic form
// ******************************************************************

/// Quadratic form macro, used to compute \f$ \int (a-b)^2 d\mu \f$.
/*! If you want to use this please be sure to understand how macro
 expansion is handled by the preprocessor (could behave strangely!) */
#define SPECTRAL_Q_FORM(A,B)	                                        \
         me->prodL2(A,A,n)                                              \
         + me->prodL2(B,B,n)                                            \
         - 2 * me->prodL2(A,B,n)

/// "Calls" SPECTRAL_Q_FORM with the \b restriction of \e A and \e B
#define SPECTRAL_RE_Q_FORM(A,B)						\
         SPECTRAL_Q_FORM(me->restriction(A,n),                      	\
			 me->restriction(B,n))

/// \brief "Calls" SPECTRAL_Q_FORM with the \b restriction of \e A and \e B.
/// and with the application of the operator \e OP
/*! The operator \e OP is applied on the restriction of \e A. The operator
    must be an operator inside Mesh API */
#define SPECTRAL_OP_RE_Q_FORM(A,B,OP)	                                \
         SPECTRAL_Q_FORM(me->OP(me->restriction(A,n),n),		\
                         me->restriction(B,n))

#endif
